package view.terrain;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.rmi.AccessException;
import java.rmi.AlreadyBoundException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;

import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;

import rmi.RemoteObserver;
import rmi.UtilitairesRmi;
import server.models.terrain.ITerrain;
import view.utils.ImageUtil;

/**
 * Classe Terrain - Représente l'affichage du jeu (le terrain, les plateaux en mouvement, le changement d'un plateau si on clique dessus).
 * @author Alexandre
 *
 */
public class TerrainView extends JPanel implements ActionListener, RemoteObserver {

	private static final String TERRAIN_JPG = "view/ressources/terrain.jpg";

	private static final long serialVersionUID = 1L;

	private ArrayList<PlateauView> plateauAuVole = new ArrayList<PlateauView>();

	private int boardWidth;
	Image imageBackground;
	private Timer timer;

	private CabaneView cabaneGauche;
	private CabaneView cabaneDroite;

	private boolean tirTouche = false;

	private KeyListener keyListener = null;
	private MouseListener mouseListener = null;
	
	private String nomClient = null;

	/**
	 * Constructeur de la classe Terrain.
	 */
	public TerrainView(ITerrain terrain, String nomClient){
		super();
		this.nomClient = nomClient;
		
		try {
			terrain.addObserver((RemoteObserver)UtilitairesRmi.getInstance().obtenirEtBind("Terrain_" + nomClient, this));
		} catch (RemoteException | AlreadyBoundException
				| NotBoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		this.keyListener = this.getKeyListener();
		this.mouseListener = this.getMouseListener();

		this.initialiseGraphic(terrain);
	}

	private void initialiseGraphic(ITerrain terrain) {
		this.setFocusable(true);

		ImageIcon icon = ImageUtil.getImageIcon(this, TerrainView.TERRAIN_JPG);

		this.imageBackground = icon.getImage();		
		this.setDoubleBuffered(true);

		this.boardWidth = icon.getIconWidth() - 55;
		try {
		this.cabaneGauche = new CabaneView(terrain.getCabaneGauche(), this.nomClient);
		this.cabaneGauche.setProperties(15, 160, 1);

		this.cabaneDroite = new CabaneView(terrain.getCabaneDroite(), this.nomClient);
		this.cabaneDroite.setProperties(boardWidth, 160, -1);
		} catch (RemoteException e) {
			//TODO gestion erreurs
			e.printStackTrace();
		}
		this.timer = new Timer(7, null);
		this.timer.addActionListener(this);
	}

	/**
	 * Lors du clique gauche de la souris, effectue des opérations si sa position est dans les dimensions du plateau.
	 * @param plateaux Liste de plateaux.
	 * @param screenX Position horizontale de la souris dans l'écran.
	 * @param screenY Position verticale de la souris dans l'écran.
	 */
	public void verifierClickPlateau(PlateauView plateau, int screenX, int screenY){
		//Si la position horizontale et verticale de la souris est dans les dimensions du plateau
		if ((screenX >= plateau.getX() 
				&& screenX <= plateau.getX() + plateau.getLargeur()) 
				&& (screenY >= plateau.getY() 
				&& screenY <= plateau.getY() + plateau.getHauteur()))
		{
			plateau.setBrokenPidge();
			this.tirTouche = true;
		} 
	}

	public boolean tirTouche()
	{
		this.timer.start();
		this.addMouseListener(this.mouseListener);
		this.addKeyListener(this.keyListener);

		while(this.timer.isRunning()) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		this.removeMouseListener(this.mouseListener);
		this.removeKeyListener(this.keyListener);

		this.plateauAuVole.clear();
		return this.tirTouche;
	}

	/**
	 * Affiche les images dans le jeu.
	 * @param g Object de type Graphics permettant d'afficher les images. 
	 */
	public void paintComponent(Graphics g){
		super.paintComponent(g);
		g.drawImage(imageBackground, 0, 0, null);
		for(PlateauView plateau : plateauAuVole){
			plateau.paint(g);
		}
	}

	/**
	 * Effectue des actions lorsqu'un événement est déclenché.
	 */
	@Override
	public void actionPerformed(ActionEvent e) {
		for (PlateauView plateau : this.plateauAuVole) {
			if (plateau.getX() >= 15 && plateau.getX() <= this.boardWidth) {
				plateau.move();
			} else {
				this.timer.stop();
				remove(plateau);
			}
		}
		repaint();
	}

	@Override
	public void update(Object object, Object arg1) {
		// TODO Auto-generated method stub

	}

	private MouseListener getMouseListener() {
		return new MouseAdapter() {
			public void mousePressed(MouseEvent mouseEvent) {
				int modifiers = mouseEvent.getModifiers();
				if ((modifiers & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK) {
					for(PlateauView plateau : plateauAuVole) {
						verifierClickPlateau(plateau, mouseEvent.getX(), mouseEvent.getY());
					}
					repaint();
				}
			}
		};
	}

	private KeyListener getKeyListener() {
		return new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				if (e.getKeyCode() == KeyEvent.VK_SPACE){
					PlateauView plateauGauche = cabaneGauche.popPlateauView();
					if (plateauGauche != null) {
						plateauAuVole.add(plateauGauche);
					}

					PlateauView plateauDroit = cabaneDroite.popPlateauView();
					if (plateauDroit != null) {
						plateauAuVole.add(plateauDroit);
					}

					validate();
				}
			}
		};
	}
}